/**
 * 请求缓存管理器
 */
class RequestCache {
  constructor(maxAge = 300) {
    this.cache = new Map();
    this.maxAge = maxAge * 1000; // 转为毫秒
  }

  get(key) {
    const entry = this.cache.get(key);
    if (!entry) return null;

    // 检查缓存是否过期
    if (Date.now() - entry.timestamp > this.maxAge) {
      this.cache.delete(key);
      return null;
    }

    return entry.data;
  }

  set(key, data) {
    this.cache.set(key, {
      data,
      timestamp: Date.now()
    });
  }

  delete(key) {
    this.cache.delete(key);
  }

  clear() {
    this.cache.clear();
  }
}

/**
 * 封装fetch请求
 * @param {string} url - 请求URL
 * @param {Object} options - fetch选项
 * @param {number} maxAge - 缓存时间(秒)
 */
const createFetchWithCache = (maxAge = 60) => {
  const cache = new RequestCache(maxAge);

  return async (url, options = {}) => {
    const cacheKey = `${url}:${JSON.stringify(options)}`;
    const cachedResponse = cache.get(cacheKey);

    if (cachedResponse) {
      return Promise.resolve(JSON.parse(JSON.stringify(cachedResponse)));
    }

    try {
      const response = await fetch(url, options);
      if (!response.ok) throw new Error(response.statusText);

      const data = await response.json();
      cache.set(cacheKey, data);
      return data;
    } catch (error) {
      console.error('Fetch error:', error);
      throw error;
    }
  };
};

/**
 * 请求合并管理器
 */
class RequestBatcher {
  constructor(batchInterval = 100) {
    this.batchRequests = new Map();
    this.timers = new Map();
    this.batchInterval = batchInterval;
  }

  addRequest(key, requestFn) {
    if (!this.batchRequests.has(key)) {
      this.batchRequests.set(key, []);
    }

    return new Promise((resolve, reject) => {
      this.batchRequests.get(key).push({ resolve, reject });

      if (!this.timers.has(key)) {
        this.timers.set(key, setTimeout(() => {
          this.executeBatch(key, requestFn);
        }, this.batchInterval));
      }
    });
  }

  async executeBatch(key, requestFn) {
    const batch = this.batchRequests.get(key) || [];
    if (batch.length === 0) return;

    this.batchRequests.delete(key);
    this.timers.delete(key);

    try {
      const data = await requestFn();
      batch.forEach(({ resolve }) => resolve(data));
    } catch (error) {
      batch.forEach(({ reject }) => reject(error));
    }
  }
}

export {
  RequestCache,
  createFetchWithCache,
  RequestBatcher
};
